from django.db import models
from django.utils import timezone
import datetime
import qrcode
from django.conf import settings
import os
from django.db.models import ObjectDoesNotExist
from django.db import models, IntegrityError
from wechatpy import WeChatPay
import random
import time
from .validators import image_validate_file_extension, image_validate_file_size, video_validate_file_extension, video_validate_file_size

# 微信支付配置
wechat_pay = WeChatPay(
    appid     = settings.APPID,
    api_key   = settings.API_KEY,
    mch_id    = settings.MCH_ID,
    mch_cert  = settings.MCH_CERT,
    mch_key   = settings.MCH_KEY,
)

def generate_out_trade_no():
    # 当前时间戳
    timestamp = int(time.time())
    # 生成一个1到9999之间的随机数
    random_num = random.randint(1, 9999)
    # 格式化订单号
    out_trade_no = f"{timestamp}{random_num:04d}"
    return out_trade_no


class VehicleRecord(models.Model):
    license_plate = models.CharField(max_length=20, verbose_name='车牌号')
    entry_time = models.DateTimeField(default=timezone.now, verbose_name='入场时间')
    exit_time = models.DateTimeField(null=True, blank=True, verbose_name='出场时间')

    image = models.ImageField(null=True, blank=True, upload_to='vehicle_images/', validators=[image_validate_file_extension, image_validate_file_size], verbose_name='图片')
    video = models.FileField(null=True, blank=True, upload_to='vehicle_videos/', validators=[video_validate_file_extension, video_validate_file_size], verbose_name='视频')

    total_duration = models.DurationField(null=True, blank=True, verbose_name='停车时长')
    fee = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True, verbose_name='停车费用')
    # bill_created = models.BooleanField(default=False, verbose_name='账单是否已生成')

    payment_link = models.URLField(null=True, blank=True, max_length=512, verbose_name='支付链接')
    payment_status = models.CharField(max_length=20, default='pending', verbose_name='支付状态', choices=[('pending', '待支付'), ('paid', '已支付')])

    class Meta:
        verbose_name = '车辆进出场记录*'
        verbose_name_plural = '车辆进出场记录*'

    # def save_model(self, request, obj, form, change):
    #     super().save_model(request, obj, form, change)
    #     if obj.exit_time and not obj.bill_created:
    #         Bill.objects.create(
    #             vehicle_record=obj,
    #             fee=obj.fee,
    #             payment_link=self.generate_payment_link(obj),
    #         )
    #         obj.bill_created = True
    #         obj.save()

    def save(self, *args, **kwargs):
        if self.exit_time:
            self.total_duration = self.exit_time - self.entry_time
            self.fee = self.calculate_fee()
            # self.payment_link=self.generate_payment_link()
        super().save(*args, **kwargs)
        if self.exit_time:
            self.payment_link=self.generate_payment_link()
        super().save(*args, **kwargs)


    def calculate_fee(self):
        # settings.py 自定义费用计算规则
        if self.total_duration:
            hours = self.total_duration.total_seconds() / 3600
            return round(hours * settings.UNIT_PRICE, 2)
        return 0

    def generate_payment_link(self):
        # 实现支付链接生成逻辑，例如使用微信支付API
        """
        创建支付链接
        :param product_description: 商品描述
        :param amount: 金额（单位：分）
        :param notify_url: 支付结果通知URL
        :return: 支付链接
        """
        # 假设支付链接是一个带有订单ID的URL, for demo only kzeng
        print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
        print("generate_payment_link")
        print(self.id)
        print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
        return "https://pay.example.com/?record_id={}".format(self.id)

        # order_data = {
        #     'body': product_description,  # 商品描述
        #     'out_trade_no': '订单号',  # 商户订单号
        #     'total_fee': amount,  # 订单总金额，单位为分
        #     'notify_url': notify_url,  # 支付结果通知的URL
        #     'trade_type': 'MWEB',  # 交易类型，MWEB为H5支付
        # }
        # prepay_id = wechat_pay.order.create(**order_data)
        # payment_link = wechat_pay.order.get_pay_url(prepay_id)
        # return payment_link

        ## 生成商户订单号 -----------------------------------------------------------------------------
        # notify_url = 'https://www.yourserver.com/payments/notify'
        # order_data = {
        #     'body': "停车费用",                         # 暂时硬编码， 商品描述
        #     'out_trade_no': generate_out_trade_no(),   # 商户订单号# 暂时使用函数生成唯一的商户订单号
        #     'total_fee':    self.fee * 100,            # 订单总金额，单位为分
        #     'notify_url':   notify_url,                # 支付结果通知的URL
        #     'trade_type':   'MWEB',                    # 交易类型，MWEB为H5支付
        # }
        # prepay_id = wechat_pay.order.create(**order_data)
        # payment_link = wechat_pay.order.get_pay_url(prepay_id)
        # return payment_link


    def get_qr_code_url(self):
        # 二维码内容
        data = self.payment_link
        print('get_qr_code_url ...')
        print(data)
        # 生成二维码
        qr = qrcode.QRCode(version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=2)
        qr.add_data(data)
        qr.make(fit=True)
        img = qr.make_image(fill='black', back_color='white')
        # 保存二维码图片的路径
        qr_code_directory = os.path.join(settings.MEDIA_ROOT, 'qr_codes')
        qr_code_filename = f'{self.pk}_qr.png'
        qr_code_path = os.path.join(qr_code_directory, qr_code_filename)
        # 确保目录存在
        if not os.path.exists(qr_code_directory):
            os.makedirs(qr_code_directory)
        # 保存二维码图片
        img.save(qr_code_path)
        # 返回二维码图片的URL
        print('qr_code_path ...')
        print(os.path.join(settings.MEDIA_URL, 'qr_codes', qr_code_filename))
        # return os.path.join(settings.MEDIA_URL, 'qr_codes', qr_code_filename)
        # return qr_code url path
        # return os.path.join(settings.MEDIA_URL, 'qr_codes', qr_code_filename)
        return "/media/qr_codes/" + qr_code_filename


    def __str__(self):
        return self.license_plate


#---------------------------------------------------------------------------------------

# 功能模块：
# 1.入库报备(入口)
# 2.出库报备（入口）
# 3.物流询价(入口)
# 4.寄钥匙(入口)
# 5.配钥匙(入口)
# 6.物品寄回(入口)
# 7车辆维修（入口）


# 一．	入库报备（入库信息+创建模板+智能识别文字）
# 1.车库名称（点击选择车库-省份+地址）
# 2.车牌号：（挂车单独添加）
# 3.车架号：（填写）
# 4.车型：（填写）
# 5.车辆类型：（选择类型：乘用车，商用车≤9.6，商用车>9.6，工程车）
# 6.车钥匙，行驶证（选择有或无）
# 7.送车人：（填写）
# 8.送车电话：（填写）
# 9.送车时间：（选择时间日期）


# 二．	出库报备
# 1.	甲方名
# 2.	车牌号
# 3.	车内物品（选择随车或留存）
# 4.	停车费用（选择甲方或提车人）
# 5.	提车人（填写）
# 6.	身份证号（填写）
# 7.	提车电话（填写）
# 8.	提车时间（选择时间）


# 三．	物流询价（含物流记录）
# 1.	甲方名（填写）
# 2.	车牌号（填写
# 3.	车架号（填写）
# 4.	车型（填写）
# 5.	车钥匙，行驶证（选择有或无）
# 6.	正常行驶（选择可以或不可以）
# 7.	出发地（填写）
# 8.	目的地（填写）


# 四．	寄钥匙(含钥匙记录查询)
# 1.	甲方名（填写）
# 2.	车牌号（填写）
# 3.	任务说明（填写）
# 4.	物流单号（填写）
# 5.	备注（填写）
# 6.	物品回寄（选择是或否）
# 7.	回寄地址（填写）


# 五．	配钥匙
# 1.	甲方名（填写）
# 2.	车牌号（填写）
# 3.	任务说明（填写）
# 4.	支付方式（选择甲方或提车人）
# 5.	备注（选填）
# 6.	物品回寄（选择是或否）
# 7.	回寄地址（填写）


# 七．	车辆维修
# 1.	甲方名（填写）
# 2.	车牌号（填写）
# 3.	维修内容（填写）
# 4.	支付方式（选择甲方或提车人）
# 5.	备注（选填）


# 八．	车辆管理（车辆状态-报备时间-搜索车牌）
# 1.	入库记录（查询-详情-状态-照片查看-删除）
# 2.	在库车辆（查询-详情-状态-照片查看-删除）
# 3.	出库记录（出库记录-照片）


# 九．	登录账户
# 1.	专属客服（姓名+点击拨打电话）
# 2.	回寄记录（查询）
# 3.	寄钥匙记录（查询）
# 4.	配钥匙记录（查询）
# 5.	维修记录（查询）
# 6.	异常记录
# 7.	子账号管理
# 8.	关于我们（介绍）
# 9.	建议反馈
# 10.	设置
#---------------------------------------------------------------------------------------


# 1. **车库信息模型 (`Garage`)**
#    - 用于存储车库的省份和地址信息。车库信息将以独立的模型形式存在，并可以进行增删查改操作。
#    - **字段**：
#      - `province`：省份
#      - `address`：地址
   
   
class Garage(models.Model):
    province = models.CharField(max_length=100, verbose_name="省份")
    address = models.CharField(max_length=255, verbose_name="地址")

    def __str__(self):
        return f"{self.province} - {self.address}"

    class Meta:
        verbose_name = "车库"
        verbose_name_plural = "车库管理"
   

# 2. **车辆信息模型 (`Vehicle`)**
#    - 用于存储车辆的基本信息，如车牌号、车架号、车型、车辆类型等。
#    - **字段**：
#      - `plate_number`：车牌号
#      - `chassis_number`：车架号
#      - `vehicle_type`：车辆类型（选择乘用车、商用车等）
#      - `model`：车型
#      - `key_present`：车钥匙是否有
#      - `registration_present`：行驶证是否有
   
   
class Vehicle(models.Model):
    LICENSE_TYPE_CHOICES = [
        ('乘用车', '乘用车'),
        ('商用车≤9.6', '商用车≤9.6'),
        ('商用车>9.6', '商用车>9.6'),
        ('工程车', '工程车'),
    ]

    plate_number = models.CharField(max_length=20, verbose_name="车牌号")
    chassis_number = models.CharField(max_length=50, verbose_name="车架号")
    vehicle_type = models.CharField(max_length=50, choices=LICENSE_TYPE_CHOICES, verbose_name="车辆类型")
    model = models.CharField(max_length=100, verbose_name="车型")
    key_present = models.BooleanField(default=False, verbose_name="车钥匙")
    registration_present = models.BooleanField(default=False, verbose_name="行驶证")

    def __str__(self):
        return self.plate_number

    class Meta:
        verbose_name = "车辆信息管理"
        verbose_name_plural = "车辆信息管理"


# 3. **入库报备模型 (`WarehouseEntry`)**
#    - 记录车辆入库时的相关信息，包括车库、送车人信息、入库时间等。
#    - **字段**：
#      - `garage`：关联的车库
#      - `vehicle`：关联的车辆
#      - `driver_name`：送车人姓名
#      - `driver_phone`：送车人电话
#      - `entry_time`：送车时间
#      - `photo`：拍照记录图片
   
   
class WarehouseEntry(models.Model):
    garage = models.ForeignKey(Garage, on_delete=models.CASCADE, verbose_name="车库名称")
    vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE, verbose_name="车辆")
    driver_name = models.CharField(max_length=100, verbose_name="送车人")
    driver_phone = models.CharField(max_length=20, verbose_name="送车电话")
    entry_time = models.DateTimeField(verbose_name="送车时间")
    photo = models.ImageField(upload_to='entry_photos/', verbose_name="拍照记录图片", blank=True, null=True)

    def __str__(self):
        return f"{self.vehicle.plate_number} - {self.garage}"

    class Meta:
        verbose_name = "入库报备"
        verbose_name_plural = "入库报备管理"


    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        vehicle_management, created = VehicleManagement.objects.get_or_create(vehicle=self.vehicle)
        vehicle_management.update_status()



# 4. **出库报备模型 (`WarehouseExit`)**
#    - 记录车辆出库时的相关信息，如甲方信息、提车人信息、出库时间等。
#    - **字段**：
#      - `vehicle`：关联的车辆
#      - `client_name`：甲方名称
#      - `items_in_car`：车内物品是否随车
#      - `parking_fee_payer`：停车费支付方（甲方或提车人）
#      - `pickup_person`：提车人
#      - `pickup_id`：提车人身份证号
#      - `pickup_phone`：提车人电话
#      - `pickup_time`：提车时间
#      - `photo`：拍照记录图片
   
   
class WarehouseExit(models.Model):
    vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE, verbose_name="车辆")
    client_name = models.CharField(max_length=100, verbose_name="甲方名")
    items_in_car = models.BooleanField(default=True, verbose_name="车内物品随车")
    parking_fee_payer = models.CharField(max_length=50, choices=[('甲方', '甲方'), ('提车人', '提车人')], verbose_name="停车费用支付方")
    pickup_person = models.CharField(max_length=100, verbose_name="提车人")
    pickup_id = models.CharField(max_length=18, verbose_name="提车人身份证号")
    pickup_phone = models.CharField(max_length=20, verbose_name="提车电话")
    pickup_time = models.DateTimeField(verbose_name="提车时间")
    photo = models.ImageField(upload_to='exit_photos/', verbose_name="拍照记录图片", blank=True, null=True)

    def __str__(self):
        return f"{self.vehicle.plate_number} - {self.client_name}"

    class Meta:
        verbose_name = "出库报备"
        verbose_name_plural = "出库报备管理"

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        vehicle_management, created = VehicleManagement.objects.get_or_create(vehicle=self.vehicle)
        vehicle_management.update_status()



# 5. **物流询价模型 (`LogisticsInquiry`)**
#    - 记录车辆物流询价的信息，如甲方名、车牌号、行驶状态、出发地和目的地等。
#    - **字段**：
#      - `vehicle`：关联的车辆
#      - `client_name`：甲方名称
#      - `can_drive`：车辆是否可以正常行驶
#      - `origin`：出发地
#      - `destination`：目的地
   
   
class LogisticsInquiry(models.Model):
    vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE, verbose_name="车辆")
    client_name = models.CharField(max_length=100, verbose_name="甲方名")
    can_drive = models.BooleanField(default=True, verbose_name="正常行驶")
    origin = models.CharField(max_length=100, verbose_name="出发地")
    destination = models.CharField(max_length=100, verbose_name="目的地")

    def __str__(self):
        return f"{self.vehicle.plate_number} - {self.client_name}"

    class Meta:
        verbose_name = "物流询价"
        verbose_name_plural = "物流询价管理"
   

# 6. **寄钥匙模型 (`KeyDelivery`)**
#    - 记录寄送车钥匙任务的信息，如甲方名、物流单号、任务说明等。
#    - **字段**：
#      - `vehicle`：关联的车辆
#      - `client_name`：甲方名称
#      - `task_description`：任务说明
#      - `logistics_number`：物流单号
#      - `notes`：备注
#      - `return_item`：是否回寄物品
#      - `return_address`：回寄地址
   
   
class KeyDelivery(models.Model):
    vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE, verbose_name="车辆")
    client_name = models.CharField(max_length=100, verbose_name="甲方名")
    task_description = models.TextField(verbose_name="任务说明")
    logistics_number = models.CharField(max_length=50, verbose_name="物流单号")
    notes = models.TextField(blank=True, verbose_name="备注")
    return_item = models.BooleanField(default=False, verbose_name="物品回寄")
    return_address = models.CharField(max_length=255, blank=True, verbose_name="回寄地址")

    def __str__(self):
        return f"{self.vehicle.plate_number} - {self.client_name}"

    class Meta:
        verbose_name = "寄钥匙"
        verbose_name_plural = "寄钥匙管理"
   

# 7. **配钥匙模型 (`KeyDuplication`)**
#    - 记录配钥匙任务的信息，如甲方名、任务说明、支付方式等。
#    - **字段**：
#      - `vehicle`：关联的车辆
#      - `client_name`：甲方名称
#      - `task_description`：任务说明
#      - `payment_by`：支付方式（甲方或提车人）
#      - `notes`：备注
#      - `return_item`：是否回寄物品
#      - `return_address`：回寄地址
   
   
class KeyDuplication(models.Model):
    vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE, verbose_name="车辆")
    client_name = models.CharField(max_length=100, verbose_name="甲方名")
    task_description = models.TextField(verbose_name="任务说明")
    payment_by = models.CharField(max_length=50, choices=[('甲方', '甲方'), ('提车人', '提车人')], verbose_name="支付方式")
    notes = models.TextField(blank=True, verbose_name="备注")
    return_item = models.BooleanField(default=False, verbose_name="物品回寄")
    return_address = models.CharField(max_length=255, blank=True, verbose_name="回寄地址")

    def __str__(self):
        return f"{self.vehicle.plate_number} - {self.client_name}"

    class Meta:
        verbose_name = "配钥匙"
        verbose_name_plural = "配钥匙管理"
   

# 8. **车辆维修模型 (`VehicleRepair`)**
#    - 记录车辆维修的信息，如甲方名、维修内容、支付方式等。
#    - **字段**：
#      - `vehicle`：关联的车辆
#      - `client_name`：甲方名称
#      - `repair_description`：维修内容
#      - `payment_by`：支付方式（甲方或提车人）
#      - `notes`：备注
   
   
class VehicleRepair(models.Model):
    vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE, verbose_name="车辆")
    client_name = models.CharField(max_length=100, verbose_name="甲方名")
    repair_description = models.TextField(verbose_name="维修内容")
    payment_by = models.CharField(max_length=50, choices=[('甲方', '甲方'), ('提车人', '提车人')], verbose_name="支付方式")
    notes = models.TextField(blank=True, verbose_name="备注")

    def __str__(self):
        return f"{self.vehicle.plate_number} - {self.client_name}"

    class Meta:
        verbose_name = "车辆维修"
        verbose_name_plural = "车辆维修管理"



class VehicleManagement(models.Model):
    vehicle = models.OneToOneField(Vehicle, on_delete=models.CASCADE, verbose_name="车辆")
    last_entry_time = models.DateTimeField(null=True, blank=True, verbose_name="最近入库时间")
    last_exit_time = models.DateTimeField(null=True, blank=True, verbose_name="最近出库时间")
    current_status = models.CharField(max_length=20, choices=[('在库', '在库'), ('已出库', '已出库')], default='在库', verbose_name="当前状态")

    def __str__(self):
        return self.vehicle.plate_number

    class Meta:
        verbose_name = "车辆出入信息"
        verbose_name_plural = "车辆出入信息"

    def update_status(self):
        last_entry = WarehouseEntry.objects.filter(vehicle=self.vehicle).order_by('-entry_time').first()
        last_exit = WarehouseExit.objects.filter(vehicle=self.vehicle).order_by('-pickup_time').first()

        self.last_entry_time = last_entry.entry_time if last_entry else None
        self.last_exit_time = last_exit.pickup_time if last_exit else None
        self.current_status = '在库' if self.last_entry_time and (not self.last_exit_time or self.last_entry_time > self.last_exit_time) else '已出库'
        self.save()




